home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 February: Tool Chest / Apple Developer CD Series Tool Chest February 1996 (Apple Computer)(1996).iso / Tool Chest / Testing & Debugging / General tools / Report Error 2.0 / DialogUtilities.c next >
Encoding:
C/C++ Source or Header  |  1992-08-17  |  19.9 KB  |  785 lines  |  [TEXT/KAHL]

  1. /*================================================================================
  2.     DialogUtilities.c
  3.     
  4.     circa 1991 by Greg Anderson
  5.     greggor@apple.com
  6.     
  7.     FREE DISTRIBUTION--use and enjoy
  8.     
  9.     This file contains various and sundry dialog box utility routines
  10. ================================================================================*/
  11. #include "DialogUtilities.h"
  12.  
  13. #ifndef __TYPES__
  14.     #include <Types.h>
  15. #endif
  16. #ifndef __SYSEQU__
  17.     #include <SysEqu.h>
  18. #endif
  19. #ifndef __TOOLUTILS__
  20.     #include <ToolUtils.h>
  21. #endif
  22. #ifndef __ERRORS__
  23.     #include <Errors.h>
  24. #endif
  25. #ifndef __MEMORY__
  26.     #include <Memory.h>
  27. #endif
  28. #ifndef __RESOURCES__
  29.     #include <Resources.h>
  30. #endif
  31. #ifndef __QUICKDRAW__
  32.     #include <Quickdraw.h>
  33. #endif
  34. #ifndef __CONTROLS__
  35.     #include <Controls.h>
  36. #endif
  37. #ifndef __DIALOGS__
  38.     #include <Dialogs.h>
  39. #endif
  40. #ifndef __SCRAP__
  41.     #include <Scrap.h>
  42. #endif
  43.  
  44. /*----------------------------------------------------------------------
  45.     MessageBox
  46.     
  47.     Display a message
  48. ----------------------------------------------------------------------*/
  49. void MessageBox( Str255 pstr )
  50. {
  51.     DialogPtr        dlog;
  52.     short            itemHit;
  53.  
  54.     dlog = GetNewDialog( 150, (Ptr)0L, (WindowPtr)-1L);
  55.  
  56.     if( dlog != nil )
  57.     {
  58.         SetPort( dlog );
  59.         ParamText( pstr, nil, nil, nil );
  60.         SelectWindow(dlog);
  61.         InstallDefaultOutline( dlog, 1 );
  62.         CenterAndShowDialog(dlog);
  63.         /*
  64.         // Wait for user to click "Okay"
  65.         */
  66.         do
  67.         {
  68.             ModalDialog((ModalFilterProcPtr) CutPasteFilter, &itemHit);
  69.         } while( itemHit != 1 );
  70.         DisposDialog(dlog);
  71.     }
  72.     else
  73.     {
  74.         DebugStr( pstr );
  75.     }
  76. }
  77.  
  78. /*----------------------------------------------------------------------
  79.     CenterAndShowDialog
  80.     
  81.     Center the specified dialog box & show it
  82.     
  83.     This code centers the dialog box on the main monitor (the one
  84.     with the menu bar) such that 1/3rd of the empty space left on
  85.     that screen is above the dialog and 2/3rds of it is below the
  86.     dialog
  87.  
  88.     Note:
  89.     
  90.     This routine looks at MBarHeight to correctly calculate the
  91.     horizontal position of the dialog box.  Accessing low memory
  92.     globals is generally an evil thing to do, but in this case
  93.     there is no good alternative.
  94. ----------------------------------------------------------------------*/
  95. void CenterAndShowDialog(DialogPtr dlog)
  96. {
  97.     short            menuHeight;
  98.     short            dlogWidth;
  99.     short            dlogHeight;
  100.     short            scrnWidth;
  101.     short            scrnHeight;
  102.     short            newDlogX;
  103.     short            newDlogY;
  104.     
  105.     /*
  106.     // Look at the low memory global 'MBarHeight' to determine the
  107.     // height of the menu bar (in pixels)
  108.     */
  109.     menuHeight = *((short*)MBarHeight);
  110.  
  111.     /*
  112.     // Calculate the size of the dialog box and the main screen
  113.     // (without the menu bar)
  114.     */
  115.     dlogWidth    = (dlog->portRect.right - dlog->portRect.left);
  116.     dlogHeight    = (dlog->portRect.bottom - dlog->portRect.top);
  117.     scrnWidth    = (qd.screenBits.bounds.right - qd.screenBits.bounds.left);
  118.     scrnHeight    = (qd.screenBits.bounds.bottom - qd.screenBits.bounds.top) - menuHeight;
  119.     /*
  120.     // Quick check: don't leave any empty space if the dialog is
  121.     // too large to fit on the main screen.  This sanity check
  122.     // really should not be necessary, though, as all dialog boxes
  123.     // should fit on 9" screens
  124.     */
  125.     if( dlogHeight > scrnHeight)
  126.         dlogHeight = scrnHeight;
  127.     /*
  128.     // Calculate the menu's new location
  129.     */
  130.     newDlogX = qd.screenBits.bounds.left + (scrnWidth - dlogWidth) / 2;
  131.     newDlogY = qd.screenBits.bounds.top + menuHeight + (scrnHeight - dlogHeight) / 3;
  132.     /*
  133.     // Move the dialog and show it
  134.     */
  135.     MoveWindow(dlog,newDlogX,newDlogY,false);
  136.     ShowWindow(dlog);
  137. }
  138.  
  139. /*----------------------------------------------------------------------
  140.     AddNewUserItem
  141.     
  142.     Creates a new useritem in the specified dialog box & returns
  143.     its item number
  144. ----------------------------------------------------------------------*/
  145. short AddNewUserItem( DialogPtr dlog )
  146. {
  147.     DialogPeek        theDialog        = (DialogPeek)dlog;
  148.     short**            itemHandle        = (short**)theDialog->items;
  149.     short            nItems            = **itemHandle + 1;
  150.     short            newItem            = 0;
  151.     DITLitem*        ditlPtr;
  152.     Size            itemHandleSize;
  153.     
  154.     itemHandleSize = GetHandleSize( (Handle)itemHandle );
  155.     SetHandleSize( (Handle)itemHandle, itemHandleSize + sizeof(DITLitem) );
  156.     if( MemError() == noErr )
  157.     {
  158.         /*
  159.         // We dereference the (potentially) unlocked itemHandle
  160.         // here; don't do any memory-moving calls until we've
  161.         // initialized the new DITL item
  162.         */
  163.         ditlPtr = (DITLitem*) ( (*itemHandle) + (itemHandleSize / sizeof(short)) );
  164.         /*
  165.         // Fill in the new fields
  166.         */
  167.         ditlPtr->placeholder = 0;
  168.         ditlPtr->itemType = userItem;
  169.         ditlPtr->extraLength = 0;
  170.         /*
  171.         // Remember / record the new number of items
  172.         */
  173.         newItem = nItems + 1;
  174.         **itemHandle = newItem - 1;
  175.     }
  176.     
  177.     return newItem;
  178. }
  179.  
  180. /*----------------------------------------------------------------------
  181.     DrawDottedLineProc
  182.     
  183.     Draw a dotted line
  184. ----------------------------------------------------------------------*/
  185. pascal void DrawDottedLineProc(DialogPtr dlog, short item)
  186. {
  187.     short                type;
  188.     Handle                itemHandle;
  189.     Rect                box;
  190.     PenState            saveState;
  191.     Point                lineStart;
  192.     Point                lineEnd;
  193.     
  194.     /*
  195.     // Save the drawing mode before doing anything with
  196.     // the pen
  197.     */
  198.     GetPenState( &saveState );
  199.     /*
  200.     // Get the bounding box of the userItem & set lineStart
  201.     // to the upper left corner and lineEnd to the lower right
  202.     // corner of the bounding rectangle
  203.     */
  204.     GetDItem(dlog, item, &type, (Handle*)&itemHandle, &box);
  205.     lineStart.h = box.left;
  206.     lineStart.v = box.top;
  207.     lineEnd.h = box.right;
  208.     lineEnd.v = box.bottom;
  209.     /*
  210.     // The line is always drawn along the longer edge
  211.     */
  212.     if( (lineEnd.h - lineStart.h) > (lineEnd.v - lineStart.v) )
  213.         lineEnd.v = lineStart.v;
  214.     else
  215.         lineEnd.h = lineStart.h;
  216.     /*
  217.     // Set the pen mode and draw the line
  218.     */
  219.     PenNormal();
  220.     PenPat(qd.gray);
  221.     MoveTo( lineStart.h, lineStart.v );
  222.     LineTo( lineEnd.h, lineEnd.v );
  223.     /*
  224.     // Restore the pen state
  225.     */
  226.     SetPenState( &saveState );
  227. }
  228.  
  229. /*----------------------------------------------------------------------
  230.     SetUserItemToDottedLine
  231.     
  232.     Make the given userItem a dotted line
  233. ----------------------------------------------------------------------*/
  234. void SetUserItemToDottedLine( DialogPtr dlog, short whichItem )
  235. {
  236.     short            type;
  237.     Handle            itemHandle;
  238.     Rect            box;
  239.     
  240.     GetDItem(dlog,whichItem,&type,&itemHandle,&box);
  241.     SetDItem(dlog,whichItem,type,(Handle)DrawDottedLineProc,&box);
  242. }
  243.  
  244. /*----------------------------------------------------------------------
  245.     DrawFrameRectProc
  246.     
  247.     Draw a frame around the specified userItem
  248. ----------------------------------------------------------------------*/
  249. pascal void DrawFrameRectProc(DialogPtr dlog, short item)
  250. {
  251.     short                type;
  252.     Handle                itemHandle;
  253.     Rect                box;
  254.     PenState            saveState;
  255.     
  256.     /*
  257.     // Save the drawing mode before doing anything with
  258.     // the pen
  259.     */
  260.     GetPenState( &saveState );
  261.     /*
  262.     // Get the bounding box of the userItem
  263.     */
  264.     GetDItem(dlog, item, &type, (Handle*)&itemHandle, &box);
  265.     /*
  266.     // Set the pen mode and draw the box
  267.     */
  268.     PenNormal();
  269.     FrameRect( &box );
  270.     /*
  271.     // Restore the pen state
  272.     */
  273.     SetPenState( &saveState );
  274. }
  275.  
  276. /*----------------------------------------------------------------------
  277.     SetUserItemToFrameRect
  278.     
  279.     Make the given userItem a dotted line
  280. ----------------------------------------------------------------------*/
  281. void SetUserItemToFrameRect( DialogPtr dlog, short whichItem )
  282. {
  283.     short            type;
  284.     Handle            itemHandle;
  285.     Rect            box;
  286.     
  287.     GetDItem(dlog,whichItem,&type,&itemHandle,&box);
  288.     SetDItem(dlog,whichItem,type,(Handle)DrawFrameRectProc,&box);
  289. }
  290.  
  291. /*----------------------------------------------------------------------
  292.     DrawDefaultProc
  293.     
  294.     Draw the thick rounded rectangle around the default button
  295.  
  296.     This routine uses Keith Rollin's algorithm, as presented in the
  297.     USENET Guide to Programming the Macintosh.  I have modified the
  298.     basic algorithm only slightly--I add two to the calculated
  299.     'buttonOval' value.  This gets better results, particularly for
  300.     buttons of the default size (18 points).
  301. ----------------------------------------------------------------------*/
  302. pascal void DrawDefaultProc(DialogPtr dlog, short item)
  303. {
  304.     short                defaultButton;
  305.     
  306.     /*
  307.     // Don't call GetDItem if the default button # has a strange value
  308.     */
  309.     defaultButton = ((DialogPeek)dlog)->aDefItem;
  310.     if( defaultButton > 0 )
  311.     {
  312.         short                type;
  313.         Handle                userHandle;
  314.         Rect                outlineBox;
  315.  
  316.         /*
  317.         // Only draw the bold outline around the default button
  318.         // if it really is a button
  319.         */
  320.         GetDItem(dlog, defaultButton, &type, &userHandle, &outlineBox);
  321.         if( type == ctrlItem + btnCtrl )
  322.         {
  323.             PenState            saveState;
  324.             short                buttonOval;
  325.  
  326.             GetPenState( &saveState );
  327.             InsetRect(&outlineBox,-4,-4);
  328.             /*
  329.             // We want to draw the thick line with a normal
  330.             // pen pattern that is 3 pixels wide
  331.             */
  332.             PenNormal();
  333.             PenSize(3,3);
  334.             /*
  335.             // If the button we are outlining is disabled,
  336.             // draw the outline with a gray pattern.
  337.             */
  338.             if( !ButtonEnabled(dlog, defaultButton ) )
  339.             {
  340.                 PenPat(qd.gray);
  341.             }
  342.             /*
  343.             // Calculate the curvature to use and draw the thick line
  344.             */
  345.             buttonOval = 2 + (outlineBox.bottom - outlineBox.top) / 2;
  346.             FrameRoundRect(&outlineBox,buttonOval,buttonOval);
  347.             
  348.             SetPenState( &saveState );
  349.         }
  350.     }
  351. }
  352.  
  353. /*----------------------------------------------------------------------
  354.     This function sets the dialog item that the default button is
  355.     drawn around.  The filterproc (below) does the drawing.
  356. ----------------------------------------------------------------------*/
  357. short InstallDefaultOutline(DialogPtr dlog, short button)
  358. {
  359.     ((DialogPeek)dlog)->aDefItem = button;
  360.     
  361.     return button;
  362. }
  363.  
  364. /*----------------------------------------------------------------------
  365.     Draw the thick square rectangle around the dialog item that accepts
  366.     keyboard input (see the System 7 Chooser for an example).
  367. ----------------------------------------------------------------------*/
  368. pascal void DrawActiveItemProc(DialogPtr dlog, short item)
  369. {
  370.     short            type;
  371.     Handle            itemHandle;
  372.     Rect            box;
  373.     PenState        saveState;
  374.     
  375.     GetPenState( &saveState );
  376.     GetDItem(dlog, item, &type, &itemHandle, &box);
  377.     PenNormal();
  378.     PenSize(2,2);
  379.     FrameRect(&box);
  380.     SetPenState( &saveState );
  381. }
  382.  
  383. /*----------------------------------------------------------------------
  384.     This function creates a useritem around the specified button & installs
  385.     a drawing proc that draws the default border around it.
  386. ----------------------------------------------------------------------*/
  387. short InstallActiveItemOutline(DialogPtr dlog, short button)
  388. {
  389.     short            userItem;
  390.     short            type;
  391.     Handle            item;
  392.     Rect            box;
  393.     Rect            userBox;
  394.     
  395.     userItem = AddNewUserItem( dlog );
  396.     if( userItem > 0 )
  397.     {
  398.         GetDItem(dlog, button, &type, &item, &box);
  399.         InsetRect(&box,-4,-4);
  400.         GetDItem(dlog, userItem, &type, &item, &userBox);
  401.         SetDItem(dlog, userItem, type, (Handle)DrawActiveItemProc, &box );
  402.     }
  403.     
  404.     return userItem;
  405. }
  406.  
  407. /*----------------------------------------------------------------------
  408.     MoveOutline
  409.     
  410.     Move a userItem around the appropriate button.
  411.     
  412.     This function should be used in conjunction with
  413.     InstallDefaultOutline to move the default button indicator
  414.     from one button to another.  If you are using the
  415.     CutPasteFilter with this routine, Return and Enter will
  416.     automatically be translated to the correct button
  417. ----------------------------------------------------------------------*/
  418. void MoveOutline(DialogPtr dlog, short userItem, short button)
  419. {
  420.     short            type;
  421.     Handle            item;
  422.     Rect            newBox;
  423.     Rect            oldBox;
  424.     
  425.     GetDItem(dlog, ((DialogPeek)dlog)->aDefItem, &type, &item, &oldBox);
  426.     InsetRect(&oldBox,-4,-4);
  427.     GetDItem(dlog, button, &type, &item, &newBox);
  428.     InsetRect(&newBox,-4,-4);
  429.     /*
  430.     // Erase the old box & invalidate the old and new
  431.     // locations to force a redraw
  432.     */
  433.     EraseRect( &oldBox );
  434.     InvalRect( &oldBox );
  435.     InvalRect( &newBox );
  436.     /*
  437.     // Remember where the default button outline moved to
  438.     */
  439.     ((DialogPeek)dlog)->aDefItem = button;
  440. }
  441.  
  442. /*----------------------------------------------------------------------
  443.     MoveActiveIndicator
  444.     
  445.     Move the active item indicator to another item.
  446.     
  447.     Note:    This routine erases and redraws the active item.
  448.             It would be better to erase & invalidate, but that's
  449.             pretty slow.
  450. ----------------------------------------------------------------------*/
  451. void MoveActiveIndicator(DialogPtr dlog, short userItem, short button)
  452. {
  453.     short            type;
  454.     Handle            item;
  455.     Rect            box;
  456.     Rect            userBox;
  457.     RgnHandle        badRgn;
  458.     RgnHandle        tmpRgn;
  459.     
  460.     GetDItem(dlog, button, &type, &item, &box);
  461.     InsetRect(&box,-4,-4);
  462.     GetDItem(dlog, userItem, &type, &item, &userBox);
  463.     SetDItem(dlog, userItem, type, item, &box );
  464.     /*
  465.     // Erase the old active item indicator
  466.     */
  467.     badRgn = NewRgn();
  468.     tmpRgn = NewRgn();
  469.     RectRgn( badRgn, &userBox );
  470.     InsetRect( &userBox, 2, 2 );
  471.     RectRgn( tmpRgn, &userBox );
  472.     DiffRgn( badRgn, tmpRgn, badRgn );
  473.     EraseRgn( badRgn );
  474.     InvalRgn( badRgn );
  475.     DisposeRgn( badRgn );
  476.     DisposeRgn( tmpRgn );
  477.     /*
  478.     // Draw the new one
  479.     */
  480.     DrawActiveItemProc( dlog, userItem );
  481. }
  482.  
  483. /*----------------------------------------------------------------------
  484.     MoveDItem
  485.     
  486.     Move a Dialog Item.
  487.     
  488.     This is not _quite_ as easy as it sounds, because if the item
  489.     is a control (such as a check box or radio button), MoveControl
  490.     must also be called.
  491.     
  492.     NOTE:    This routine doesn't quite work, because it does not
  493.             erase or redraw the item that moved unless it is
  494.             a control.  Tsk tsk.
  495. ----------------------------------------------------------------------*/
  496. void MoveDItem( DialogPtr dlog, short itemNumber, short h, short v )
  497. {
  498.     Handle            itemHandle;
  499.     short            itemType;
  500.     Rect            box;
  501.     
  502.     /*
  503.     // Get some useful information about the DItem to move
  504.     */
  505.     GetDItem( dlog, itemNumber, &itemType, (Handle*)&itemHandle, &box );
  506.     /*
  507.     // Move the bounding box to the correct location
  508.     */
  509.     box.bottom += (v - box.top);
  510.     box.right += (h - box.left);
  511.     box.top = v;
  512.     box.left = h;
  513.     /*
  514.     // Set the bounding box of the item to move
  515.     */
  516.     SetDItem( dlog, itemNumber, itemType, (Handle)itemHandle, &box );
  517.     /*
  518.     // If the item is a control, call MoveControl
  519.     */
  520.     if( (itemType & ctrlItem) != 0 )
  521.     {
  522.         MoveControl( (ControlHandle)itemHandle, h, v );
  523.     }
  524. }
  525.  
  526. /*----------------------------------------------------------------------
  527.     SetItemHandle
  528.     
  529.     Set the item handle of a dialog item (particularly useful for
  530.     useritems)
  531. ----------------------------------------------------------------------*/
  532. void SetItemHandle( DialogPtr dlog, short whichItem, Handle newItem )
  533. {
  534.     short            type;
  535.     Handle            itemHandle;
  536.     Rect            box;
  537.     
  538.     GetDItem(dlog,whichItem,&type,&itemHandle,&box);
  539.     SetDItem(dlog,whichItem,type,newItem,&box);
  540. }
  541.  
  542. /*----------------------------------------------------------------------
  543.     GetItemPoint
  544.     
  545.     Returns the location of a given dialog item
  546. ----------------------------------------------------------------------*/
  547. Point GetItemPoint( DialogPtr dlog, short itemNum )
  548. {
  549.     Point        loc;
  550.     short        type;
  551.     Handle        item;
  552.     Rect        box;
  553.     
  554.     GetDItem(dlog,itemNum, &type, &item, &box);
  555.     loc.h = box.left;
  556.     loc.v = box.top;
  557.     return( loc );
  558. }
  559.  
  560. /*----------------------------------------------------------------------
  561.     ButtonEnabled
  562.     
  563.     This routine is used by DrawDefaultProc and CutPasteFilter
  564.     to determine if the default button is enabled
  565. ----------------------------------------------------------------------*/
  566. Boolean ButtonEnabled(DialogPtr dlog, short item)
  567. {
  568.     ControlHandle        buttonHandle = nil;
  569.     Rect                buttonBox;
  570.     short                type;
  571.  
  572.     GetDItem(dlog, item, &type, (Handle*)&buttonHandle, &buttonBox);
  573.     if( (buttonHandle == nil) || ((type & ctrlItem) == 0) )
  574.         return false;
  575.     
  576.     /*
  577.     // A contrlHilite value of 255 indicates that the button
  578.     // is disabled
  579.     */
  580.     return ( (*buttonHandle)->contrlHilite != 255 );
  581. }
  582.  
  583. /*----------------------------------------------------------------------
  584.     EnableButton
  585.     
  586.     This simple routine will enable or disable a button
  587. ----------------------------------------------------------------------*/
  588. pascal void EnableButton(DialogPtr dlog, short button,Boolean enable)
  589. {
  590.     ControlHandle        buttonHandle;
  591.     short                type;
  592.     Rect                box;
  593.     
  594.     GetDItem(dlog,button,&type,(Handle*)&buttonHandle,&box);
  595.     HiliteControl(buttonHandle, enable ? 0 : 255);
  596. }
  597.  
  598. /*----------------------------------------------------------------------
  599.     FlashDlogItem
  600.     
  601.     Momentarily hilite a dialog button
  602. ----------------------------------------------------------------------*/
  603. void FlashDlogItem( DialogPtr dlog, short itemNum )
  604. {
  605.     ControlHandle        itemHandle;
  606.     short                itemType;
  607.     Rect                iRect;
  608.     long                ticky;
  609.     
  610.     GetDItem(dlog,itemNum,&itemType,(Handle*)&itemHandle,&iRect);
  611.     HiliteControl(itemHandle,1);
  612.     Draw1Control(itemHandle);
  613.     ticky = TickCount() + 10;
  614.     while( ticky > TickCount() );
  615.     HiliteControl(itemHandle,0);
  616.     Draw1Control(itemHandle);
  617. }
  618.  
  619. /*----------------------------------------------------------------------
  620.     CutPasteFilter
  621.     
  622.     This filter, when passed to ModalDialog, will allow the user to
  623.     cut, copy and paste by pressing command-X, command-C or command-V,
  624.     respectively.  It also checks if the cursor is over an editText
  625.     item, and if so, the cursor is changed into an IBeam.
  626.     
  627.     This procedure may be used as the filterProc of any dialog that
  628.     uses ModelDialog().  Note that this filter calls FlashDlogItem(),
  629.     above.  In all other respects, it is completely self-contained.
  630.     
  631.     This routine always translates command-. to button #2.
  632.     Your dialog box should have button #2 set up as a
  633.     'Cancel' button if you use this routine.
  634. ----------------------------------------------------------------------*/
  635. pascal Boolean CutPasteFilter( DialogPtr dlog, EventRecord* event, short* item )
  636. {
  637.     DialogRecord    *dp = (DialogRecord *)dlog;
  638.     TEHandle        te;
  639.     Str255            Pstr;
  640.     long            num;
  641.     char            key;
  642.     char            code;
  643.     short            itemType = statText;
  644.     short            itemNum;
  645.     Handle            itemHandle;
  646.     Point            mouse;
  647.     Rect            tRect;
  648.     
  649.     te = dp->textH;
  650.     /*
  651.     // Adjust the cursor to an iBeam or Arrow as appropriate
  652.     */    
  653.     GetMouse( &mouse );
  654.     itemNum = FindDItem(dlog,mouse) + 1;
  655.     if( itemNum > 0 )
  656.         GetDItem(dlog,itemNum,&itemType,&itemHandle,&tRect);
  657.     SetCursor( (itemType == editText) ? *GetCursor(iBeamCursor) : &qd.arrow);
  658.     
  659.     /*
  660.     // If the event is an update event, check to see
  661.     // if it is for this dialog or for some other window
  662.     */
  663.     if( (event->what == updateEvt) )
  664.     {
  665.         /*
  666.         // If the update event is for this dialog box,
  667.         // then draw the default button
  668.         */
  669.         if( StripAddress((DialogPtr)event->message) == StripAddress(dlog) )
  670.         {
  671.             /*
  672.             // The 'item' parameter is ignored, but we
  673.             // don't have any better value to pass to
  674.             // it than the item # of the default button
  675.             */
  676.             DrawDefaultProc(dlog, ((DialogPeek)dlog)->aDefItem );
  677.         }
  678.     }
  679.     
  680.     /*
  681.     // Is the event a key-down event?
  682.     */
  683.     if( (event->what == keyDown) || (event->what == autoKey) )
  684.     {
  685.         key  = (event->message & charCodeMask);
  686.         code = (event->message &  keyCodeMask) >> 8;
  687.         /*
  688.         // If F2, F3 or F4 (cut, copy or paste) are pressed,
  689.         // forge a Command-X, C or V and handle the appropriate
  690.         // command below.
  691.         */
  692.         switch( code )
  693.         {
  694.             case 120:
  695.             {
  696.                 event->modifiers |= cmdKey;
  697.                 key = 'x';
  698.                 break;
  699.             }
  700.             
  701.             case  99:
  702.             {
  703.                 event->modifiers |= cmdKey;
  704.                 key = 'c';
  705.                 break;
  706.             }
  707.             
  708.             case 118:
  709.             {
  710.                 event->modifiers |= cmdKey;
  711.                 key = 'v';
  712.                 break;
  713.             }
  714.         }
  715.         /*
  716.         // Is the command key down?
  717.         */
  718.         if( event->modifiers & cmdKey )
  719.         {
  720.             switch( key )
  721.             {
  722.                 /*
  723.                 // Command-X, C and V are cut, copy and paste.
  724.                 */
  725.                 case 'x':
  726.                 case 'c':
  727.                 {
  728.                     ZeroScrap();
  729.                     if( key == 'x' )
  730.                         DlgCut( dlog );
  731.                     else
  732.                         DlgCopy( dlog );
  733.                     if( TEToScrap() != noErr )
  734.                         SysBeep(120);
  735.                     return true;
  736.                 }
  737.                                         
  738.                 case 'v':
  739.                 {
  740.                     if( TEFromScrap() == noErr )
  741.                         DlgPaste( dlog );
  742.                     else
  743.                         SysBeep(120);
  744.                     return true;
  745.                 }
  746.                 
  747.                 /*
  748.                 // Command-. cancels
  749.                 */
  750.                 case '.':
  751.                 {
  752.                     *item = 2;
  753.                     FlashDlogItem( dlog, *item );
  754.                     return true;
  755.                 }
  756.             }
  757.             /*
  758.             // All other command-key combinations do nothing
  759.             */
  760.             event->what = nullEvent;
  761.             return false;
  762.         }
  763.         /*
  764.         // If RETURN or ENTER was pressed, exit with
  765.         // itemHit = ((DialogPeek)dlog)->aDefItem--but only if the
  766.         // default button is enabled.
  767.         */
  768.         if( ((key == 13) || (key == 3)) && ButtonEnabled(dlog,((DialogPeek)dlog)->aDefItem) )
  769.         {
  770.             *item = ((DialogPeek)dlog)->aDefItem;
  771.             FlashDlogItem( dlog, *item );
  772.             return true;
  773.         }
  774.         /*
  775.         // Swallow non-printing characters
  776.         */
  777.         if( (key < ' ') && (key != 8) && (key != 9) )
  778.         {
  779.             event->what = nullEvent;
  780.             return false;
  781.         }
  782.     }
  783.     return false;
  784. }
  785.